package com.joey.protocol;

import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.joey.base.util.LogUtils;
import com.joey.base.util.SharedPreferenceUtils;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

/**
 * Created by Joey on 2018/3/27.
 */

public class NetClient {

    /**
     * file media type, like "text/plain; charset=utf-8", appropriate for use in a
     * Content-Type header.{@code ContentType}
     */
    private String mFileType;
    private static OkHttpClient client;

    private static boolean offline; // 是否离线标记

    public static void setOffLine(boolean flag) {
        offline = flag;
    }

    public static boolean getOffline() {
        return offline;
    }

    private String tag;

    private static Map<String, String> extraMap = new HashMap<>();
    /**
     * unit milliSeconds
     */
    private static long mTimeOut = 60 * 1000;

    public NetClient() {
        this("default");
    }

    public NetClient(String tag) {
        this.tag = tag;
    }

    /**
     * set client time out unit milliseconds
     */
    public static void setTimeOut(long timeOut) {
        mTimeOut = timeOut;
    }

    public static void addExtra(String key, String value) {
        extraMap.put(key, value);
        SharedPreferenceUtils.getInstance().putString(key, value);
    }

    public static String getExtraValue(String key) {
        String value;
        if (extraMap.isEmpty()) {
            value = SharedPreferenceUtils.getInstance().getString(key);
        } else {
            value = extraMap.get(key);
        }
        return value;
    }

    public static void cleanExtra() {
        if (extraMap.isEmpty()) {
            return;
        }
        for (String key : extraMap.keySet()) {
            SharedPreferenceUtils.getInstance().remove(key);
        }
        extraMap.clear();
    }

    /**
     * 用于双瑞通信的格式化
     *
     * @param params
     */
    private Map<String, String> sunruiToken(Map<String, String> params) {
        if (extraMap.isEmpty()) {
            return params;
        }
        JsonObject object = new JsonObject();
        if (params == null) {
            params = new HashMap<>();
        } else {
            String json = params.get("jsonData");
            if (!TextUtils.isEmpty(json)) {
                object = new Gson().fromJson(json, JsonObject.class);
            }
        }
        for (String key : extraMap.keySet())
            object.addProperty(key, extraMap.get(key));
        params.put("jsonData", new Gson().toJson(object));
        return params;
    }

    public void uploads(String url, Map<String, String> mapParams, NetResponseListener responseListener, File... files) {
        FileProperty property = new FileProperty(files);
        uploadLots(url, mapParams, responseListener, property);
    }

    public void uploadLots(String url, Map<String, String> mapParams, NetResponseListener responseListener, FileProperty... fileProperties) {
        Map<String, String> map = sunruiToken(mapParams);
        excute(createRequest(url, createMultipartBody(map, responseListener, fileProperties)), responseListener);
    }

    public void uploadLots(String url, String methodName, Map<String, String> mapParams, NetResponseListener responseListener, FileProperty... fileProperties) {
        uploadLots(url + methodName, mapParams, responseListener, fileProperties);
    }

    public void uploads(String url, String methodName, Map<String, String> mapParams, NetResponseListener responseListener, File... files) {
        uploads(url + methodName, mapParams, responseListener, files);
    }

    public void httpPost(String url, Map<String, String> mapParams, NetResponseListener responseListener) {
        Map<String, String> map = sunruiToken(mapParams);
        excute(createRequest(url, createFormBody(map)),
                responseListener);
    }

    public void httpPost(String url, String methodName, Map<String, String> mapParams, NetResponseListener responseListener) {
        httpPost(url+methodName,mapParams,responseListener);
    }

    public void httpGet(String url, NetResponseListener responseListener) {
        excute(createRequest(url, null), responseListener);
    }

    public void httpGet(String url, String methodName, NetResponseListener responseListener) {
        excute(createRequest(url + methodName, null),
                responseListener);
    }

    public void download(String url, NetResponseListener responseListener) {
        excute(createRequest(url, null), responseListener);
    }

    public void download(String url, String methodName, NetResponseListener responseListener) {
        excute(createRequest(url + methodName, null), responseListener);
    }

    private Request createRequest(String url, RequestBody body) {
        LogUtils.a("url = " + url);
        final Request.Builder builder = new Request.Builder();
        builder.url(url)
                .tag(tag);
        if (body == null) {
            builder.get();
        } else {
            builder.post(body);
        }
        return builder.build();

    }

    private FormBody createFormBody(Map<String, String> params) {
        FormBody.Builder formBody = new FormBody.Builder();//创建表单请求体
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                formBody.add(key, params.get(key));
            }
            LogUtils.a("map = " + params.toString());
        }
        return formBody.build();
    }

    private MultipartBody createMultipartBody(Map<String, String> params, OnUploadListener listener, FileProperty... properties) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        if (params != null && !params.isEmpty()) {
            for (String key : params.keySet()) {
                builder.addFormDataPart(key, params.get(key));
            }
            LogUtils.a("map = " + params.toString());
        }

        if (properties == null || properties.length == 0) {
            return builder.build();
        }
        for (FileProperty property : properties) {
            int i = 0;
            File[] files = property.getFiles();
            if (files != null && files.length > 0) {
                for (File f : files) {
                    RequestBody body = UploadRequestBody.createCustomRequestBody(MultipartBody.FORM, i, listener, f);
                    builder.addFormDataPart(property.getKey(), f.getName(), body);
                    i++;
                }
            }
        }

        return builder.build();

    }

    private void excute(Request request, NetResponseListener responseListener) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(mTimeOut, TimeUnit.MILLISECONDS);
        builder.readTimeout(mTimeOut * 2 , TimeUnit.MILLISECONDS);
        builder.writeTimeout(mTimeOut *2, TimeUnit.MILLISECONDS);
        if (client == null)
            client = builder.build();
        client.newCall(request).enqueue(responseListener);
        responseListener.onStart();
    }

    public static void cancel(String tag) {
        if (tag == null || client == null) return;
        for (Call call : client.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
        for (Call call : client.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }

    }

    public static void cacelAll() {
        if (client == null) return;
        for (Call call : client.dispatcher().queuedCalls()) {
            call.cancel();
        }
        for (Call call : client.dispatcher().runningCalls()) {
            call.cancel();
        }
    }

}
